package com.example.flow

import kotlinx.coroutines.flow.*
import kotlinx.coroutines.runBlocking
import org.junit.Test


/**
 * 流末端操作符测试
 *
 * @author zhouronghua
 * @time 2022/1/7 8:41 上午
 */
class FlowTerminalTest {

    /**
     * 测试流末端操作符reduce
     * 说明：使用 reduce 与 fold 将流规约到单个值。
     *
     * @author zhouronghua
     * @time 2022/1/7 8:42 上午
     */
    @Test
    fun test_flow_reduce() = runBlocking {
       val sum =  (1..5).asFlow()
            .map { it * it }
            .reduce { a, b -> a + b }
        println("平方求和结果：$sum")
    }

    /**
     * 测试流末端操作符first
     * 说明：获取接收端流的第一个元素
     *
     * @author zhouronghua
     * @time 2022/1/7 8:42 上午
     */
    @Test
    fun test_flow_first() = runBlocking {
        val firstValue =  (1..5).asFlow()
            .map { it * it }
            .first()
        println("接收端第一个元素：$firstValue")

        (1..5).asFlow()
            .mapLatest {
                it * it
            }.collect {
                println("接收端元素：$it")
            }
    }

    /**
     * 测试流末端操作符single
     * 说明：获取接收端流的第一个元素
     *
     * @author zhouronghua
     * @time 2022/1/7 8:42 上午
     */
    @Test
    fun test_flow_single() = runBlocking {
        val firstValue =  (1..5).asFlow()
            .map { it * it }
            .single()
        println("接收端第一个元素：$firstValue")
    }

    /**
     * 测试流末端操作符toList
     * 说明：将流转换为列表处理
     *
     * @author zhouronghua
     * @time 2022/1/7 8:42 上午
     */
    @Test
    fun test_flow_toList() = runBlocking {
        val list = (1 .. 5).asFlow()
            .map { it * it }
            .toList()
        println("接收端第一个元素：$list")
    }

    /**
     * 测试流末端操作符toSet
     * 说明：将流转换为Set处理(元素去重)
     *
     * @author zhouronghua
     * @time 2022/1/7 8:42 上午
     */
    @Test
    fun test_flow_toSet() = runBlocking {
        val set = flowOf(1,1,2,8,9,3,2,1)
            .map { it * it }
            .toSet()
        println("接收端第一个元素：$set")
    }

//    @Test
//    fun test_flow_toCollection() = runBlocking {
//        val set = flowOf(1,1,2,8,9,3,2,1)
//            .map { it * it }
//            .toCollection()
//        println("接收端第一个元素：$set")
//    }

    /**
     * 限长操作符
     * 说明: 只取前面定长的元素
     *
     * @author zhouronghua
     * @time 2022/1/7 10:07 下午
     */
   @Test
    fun test_flow_take() = runBlocking {
        println("只获取前面100个元素")
        (1..1000).asFlow().take(100)
            .collect{
                println("收集元素 $it")
            }
    }
}
